﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Sgr.BackGroundTasks;
using Sgr.Email;
using Sgr.Email.BackGroundTasks;
using Sgr.Utilities;

namespace Microsoft.Extensions.DependencyInjection
{
    /// <summary>
    ///
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        // 验证错误消息
        private static readonly string[] ValidationMessages = new[]
        {
            "SMTP服务器地址不能为空",
            "无效的SMTP服务器端口号，应在1-65535之间",
            "连接超时时间必须大于0秒",
            "无效的验证类型，应为：None、StartTls或SslOnConnect",
            "SMTP用户名不能为空",
            "SMTP密码不能为空",
            "默认发件人地址不能为空",
            "最大重试次数不能小于0",
            "重试间隔时间必须大于0秒",
            "发送频率限制必须大于0",
            "最大并发发送数必须大于0",
            "默认发件人地址格式无效"
        };

        // 有效的验证类型
        private static readonly string[] ValidVerificationTypes = new[]
        {
            "none",
            "starttls",
            "sslonconnect"
        };

        /// <summary>
        /// 添加邮件发送功能
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configureOptions"></param>
        /// <returns></returns>
        public static IServiceCollection AddEmail(this IServiceCollection services, Action<EmailOptions>? configureOptions = null)
        {
            // 检查是否已经注册
            if (services.Any(x => x.ServiceType == typeof(ISmtpService)))
            {
                return services;
            }

            services.TryAddTransient<IEmailAddressValidator, EmailAddressValidator>();
            services.TryAddTransient<ISmtpService, SmtpService>();

            services.AddOptions<EmailOptions>()
                .BindConfiguration("Sgr:Email")
                .PostConfigure(options =>
                {
                    if (string.IsNullOrEmpty(options.Password))
                    {
                        options.Password = GetEmailPassword() ?? "default"; //此处设置default避免启动时异常
                    }

                    configureOptions?.Invoke(options);
                })
                .Validate(options =>
                {
                    try
                    {
                        ValidateSmtpServerConfig(options);
                        ValidateAuthenticationInfo(options);
                        ValidateSendingConfig(options);
                        ValidateEmailAddress(options.DefaultFromAddress);

                        return true;
                    }
                    catch (OptionsValidationException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        throw new OptionsValidationException(nameof(EmailOptions), typeof(EmailOptions),
                            new[] { $"配置验证失败: {ex.Message}" });
                    }
                });

            services.AddBackGroundTask<EmailSenderBackGroundTask, EmailSenderData>();
            services.Configure<BackGroundTaskOptions>(opts =>
            {
                opts.RegistBackGroundTask<EmailSenderBackGroundTask>();
            });

            return services;
        }

        private static void ValidateSmtpServerConfig(EmailOptions options)
        {
            if (string.IsNullOrEmpty(options.Host))
                ThrowValidationException(0);

            if (options.Port <= 0 || options.Port > 65535)
                ThrowValidationException(1);

            if (options.TimeoutSeconds <= 0)
                ThrowValidationException(2);

            if (!IsValidVerificationType(options.VerificationType))
                ThrowValidationException(3);
        }

        private static void ValidateAuthenticationInfo(EmailOptions options)
        {
            if (options.AuthenticationType != SmtpAuthenticationType.Anonymous)
            {
                if (string.IsNullOrEmpty(options.UserName))
                    ThrowValidationException(4);

                if (string.IsNullOrEmpty(options.Password))
                    ThrowValidationException(5);
            }
        }

        private static void ValidateSendingConfig(EmailOptions options)
        {
            if (string.IsNullOrEmpty(options.DefaultFromAddress))
                ThrowValidationException(6);

            if (options.MaxRetryCount < 0)
                ThrowValidationException(7);

            if (options.RetryIntervalSeconds <= 0)
                ThrowValidationException(8);

            if (options.RateLimit <= 0)
                ThrowValidationException(9);
        }

        private static void ValidateEmailAddress(string email)
        {
            var emailValidator = new EmailAddressValidator();
            if (!emailValidator.Validate(email))
                ThrowValidationException(11);
        }

        private static bool IsValidVerificationType(string verificationType)
            => Array.IndexOf(ValidVerificationTypes, verificationType.ToLowerInvariant()) != -1;

        private static void ThrowValidationException(int messageIndex)
            => throw new OptionsValidationException(
                nameof(EmailOptions),
                typeof(EmailOptions),
                new[] { ValidationMessages[messageIndex] });

        /// <summary>
        /// 获取JWT密钥
        /// </summary>
        private static string? GetEmailPassword()
        {
            const string ENV_EMAIL_PASSWORD_KEY = "SGR_EMAIL_KEY";

            return EnvironmentHelper.GetEnvironmentVariable(ENV_EMAIL_PASSWORD_KEY);
        }
    }
}